package com.crawler.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.SSLContext;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
/**   
 * @ClassName:     HttpUtils   
 * @Description:   http工具类
 * @author:        wl
 * @date:          2016年11月27日 下午9:00:39  
 * 本代码实现java原生的HttpsURLConnection请求   ，以及框架HttpClient
 * 本工具类为了方便单个使用，使学习者更加方便学习，因此不做代码抽取
 * 返回的消息统一为String类型
 */  
public class HttpUtils {
	private static String ENCODED = "UTF-8";
	//请求超时时间
	private static int CONNECTTIMEOUT = 10000;
	private static int READTIMEOUT = 10000;
	
	/**   
	 * @Title:         HttpURLConnectionPost   
	 * @Description:   java原生HTTP post请求  
	 * @param:         @param address 请求地址
	 * @param:         @param dataType 请求数据 根据Content-Type决定data的格式(普通的表单或者json)
	 * @param:         @param property property请求参数设置(类型多种) 
	 * @return:        String   String为返回的数据 
	 * @author:        wl  
	 * @date:          2017年7月31日 下午2:39:41   
	 *   
	 */  
	public static String HttpURLConnectionPost(String address,String data,Map<String,String> head){
		try {
			//获取访问地址
			URL url = new URL(address);
			//获取连接
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			//设置连接参数
			connection.setDoInput(true);
			connection.setDoOutput(true);
			connection.setConnectTimeout(CONNECTTIMEOUT);
			connection.setReadTimeout(READTIMEOUT);
			connection.setRequestMethod("POST");
			if(head!=null){
				for (Entry<String, String> entry : head.entrySet()) {
					connection.setRequestProperty(entry.getKey(), entry.getValue());
				}
			}
			connection.connect();
			if(StringUtils.isNotEmpty(data)){
				//获取输出流
				OutputStream outputStream = connection.getOutputStream();
				outputStream.write(data.getBytes());
				outputStream.flush();
				outputStream.close();
			}
			StringBuilder builder = new StringBuilder();
			//获取返回的数据
			builder.append(new String(getByte(connection.getInputStream()),ENCODED));
			return builder.toString();
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return e.getMessage();
		} catch (ProtocolException e) {
			e.printStackTrace();
			return e.getMessage();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return e.getMessage();
		} catch (IOException e) {
			e.printStackTrace();
			return e.getMessage();
		} catch (Exception e) {
			e.printStackTrace();
			return e.getMessage();
		}
	}
	
	/**  
	 * 
	 * @Title:         HttpURLConnectionGet   
	 * @Description:   get请求   
	 * @param:         address 请求地址
	 * @param:         head 请求头
	 * @return:        返回的信息   
	 * @author:        wl  
	 * @date:          2017年7月31日 下午3:39:16   
	 * 
	 */  
	public static String HttpURLConnectionGet(String address,Map<String,String> head){
		try {
			//获取访问地址
			URL url = new URL(address);
			//获取连接
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			//设置连接参数
			connection.setDoInput(true);
			connection.setDoOutput(true);
			connection.setConnectTimeout(CONNECTTIMEOUT);
			connection.setReadTimeout(READTIMEOUT);
			connection.setRequestMethod("GET");
			if(head!=null){
				//设置请求信息
				for (Entry<String, String> pro : head.entrySet()) {
					connection.setRequestProperty(pro.getKey(), pro.getValue());
				}
			}
			connection.connect();
			StringBuilder builder = new StringBuilder();
			//获取返回的数据
			builder.append(new String(getByte(connection.getInputStream()),ENCODED));
			return builder.toString();
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return e.getMessage();
		} catch (ProtocolException e) {
			e.printStackTrace();
			return e.getMessage();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return e.getMessage();
		} catch (IOException e) {
			e.printStackTrace();
			return e.getMessage();
		} catch (Exception e) {
			e.printStackTrace();
			return e.getMessage();
		}		
	}
	
	/**   
	 * @Title:         HttpsClientGet   
	 * @Description:   get	请求
	 * @param:         address 请求地址
	 * @param:         head
	 * @param:         params
	 * @param:         @throws Exception      
	 * @return:        String   
	 * @author:        wl  
	 * @date:          2017年7月31日 下午3:15:48   
	 */  
	public static String HttpsClientGet(String address,Map<String,String> head,Map<String,String> params) {
		StringBuilder builder = new StringBuilder();
		try {
			//1、添加请求参数
			if(params!=null){
				List<NameValuePair> param = new ArrayList<NameValuePair>();
				for (Entry<String, String> entry : params.entrySet()) {
					param.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
				UrlEncodedFormEntity encodedFormEntity = new UrlEncodedFormEntity(param,ENCODED);
				String str = EntityUtils.toString(encodedFormEntity);
				address = address+"?"+str;
			}
			//2、信任所有证书
			HttpClient client = createSSLClientDefault();
			HttpGet httpGet = new HttpGet(address);
			//3、添加请求头
			if(head!=null){
				for (Entry<String, String> entry : head.entrySet()) {
					httpGet.setHeader(entry.getKey(), entry.getValue());
				}
			}
			//4、发送请求
			HttpResponse response = client.execute(httpGet);
			builder = new StringBuilder();
			//5、返回相应体
			builder.append(new String(getByte(response.getEntity().getContent()),ENCODED));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (UnsupportedOperationException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return builder.toString();
	}
	
	/**   
	 * @Title:         HttpsClientPost   
	 * @Description:   post请求   
	 * @param:         @param address 请求地址
	 * @param:         @param head 头部信息
	 * @param:         @param params form参数
	 * @param:         @param jsonOrXml 如果请求是json或者xml
	 * @return:        返回的信息   
	 * @author:        wl  
	 * @date:          2017年7月31日 下午3:49:32   
	 */  
	public static String HttpsClientPost(String address,Map<String,String> head,Map<String,String> params,String jsonOrXml){
		StringBuilder builder = null;
		try {
			HttpClient client = createSSLClientDefault();
			//设置请求和传输超时时间
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(READTIMEOUT).setConnectTimeout(CONNECTTIMEOUT).build();
			HttpPost httpPost = new HttpPost(address);
			httpPost.setConfig(requestConfig);
			//设置请求内容
			if(params!=null || jsonOrXml!=null){
				if(head!=null&& head.get("Content-Type").equals("application/json")){
					//接收json形式的参数
					StringEntity entity = new StringEntity(jsonOrXml,ENCODED);
					entity.setContentEncoding(ENCODED);
					entity.setContentType("application/json");
					httpPost.setEntity(entity);					
				}else if (head!=null&& head.get("Content-Type").equals("application/xml")) {
					//接收xml形式的参数
					StringEntity entity = new StringEntity(jsonOrXml,ENCODED);
					entity.setContentEncoding(ENCODED);
					entity.setContentType("application/xml");
					httpPost.setEntity(entity);					
				}else {
					//parameters 是键值对的形式
					List<NameValuePair> parameters = new ArrayList<NameValuePair>();
					for (Entry<String, String> entry : params.entrySet()) {
						parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
					}
					UrlEncodedFormEntity encodedFormEntity = new UrlEncodedFormEntity(parameters,ENCODED);
					httpPost.setEntity(encodedFormEntity);			
				}
				
			}
			//3、添加请求头
			if(head!=null){
				for (Entry<String, String> entry : head.entrySet()) {
					httpPost.setHeader(entry.getKey(), entry.getValue());
				}
			}			
			HttpResponse response = client.execute(httpPost);
			builder = new StringBuilder();
			builder.append(new String(getByte(response.getEntity().getContent()),ENCODED));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (UnsupportedOperationException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return builder.toString();
	}
	
	public static byte[] getByte(InputStream inputStream) throws Exception{
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		int len = 0;
		byte[] b = new byte[1024];
		while ((len = inputStream.read(b))!=-1) {
			byteArrayOutputStream.write(b, 0, len);
			byteArrayOutputStream.flush();
		}
		inputStream.close();
		byteArrayOutputStream.close();
		return byteArrayOutputStream.toByteArray();
	} 
	
	/** 
	* @Title: createSSLClientDefault 
	* @Description: 认证所有的证书
	* @throws 
	*/ 
	public static CloseableHttpClient createSSLClientDefault(){
		try {
		      SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
		                 //信任所有证书
		             public boolean isTrusted(X509Certificate[] chain,
		                                 String authType) throws CertificateException {
		                     return true;
		                 }
		             }).build();
		             SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
		             return HttpClients.custom().setSSLSocketFactory(sslsf).build();
		         } catch (KeyManagementException e) {
		             e.printStackTrace();
		         } catch (NoSuchAlgorithmException e) {
		             e.printStackTrace();
		         } catch (KeyStoreException e) {
		             e.printStackTrace();
		         }
		         return  HttpClients.createDefault();
		}	
	
	public static void main(String[] args) {

//		String result = null;
//		String getUrl = "https://kyfw.12306.cn/otn/leftTicket/init";
////		result = HttpUtils.HttpsClientGet(getUrl, null, null);
////		result = HttpUtils.HttpURLConnectionGet(getUrl, null);
//		System.out.println(result);
//		String post = "<xml>"+
// "<ToUserName><![CDATA[oeuzt0Swel-9Qcw2YFtIaAmGyPFA]]></ToUserName>"+
// "<FromUserName><![CDATA[gh_ce2d0399ca1a]]></FromUserName>"+
// "<CreateTime>1348831860</CreateTime>"+
// "<MsgType><![CDATA[text]]></MsgType>"+
// "<Content><![CDATA[this is a test]]></Content>"+
// "<MsgId>1234567890123456</MsgId>"+
// "</xml>";
//		Map<String,String> head = new HashMap<String, String>();
//		head.put("Content-Type", "application/xml");
//		String res = HttpUtils.HttpsClientPost("http://114.215.164.66/test/checkSignature", head, null, post);
//	System.out.println(res);
		Map<String,String> head = new HashMap<String, String>();
		head.put("Content-Type", "application/json");
		String jsonOrXml = "[{\"docId\": \"00001\",\"text\": \"投名装\"} ]";
		System.out.println(
		HttpUtils.HttpsClientPost("http://114.215.164.66/kb/proofread/4", head, null, jsonOrXml)
				);
	}
} 
  